package logic;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import constants.BonusType;
import constants.BrickColor;
import constants.PercentNumber;
import constants.WallType;

import database.DataConnection;
import entities.AmmunitionCounter;
import entities.Ball;
import entities.Bat;
import entities.Bonus;
import entities.Brick;
import entities.Level;
import entities.Life;
import entities.Rocket;
import entities.Score;
import entities.Wall;

/** BBDataSaver's class.
 * @author Jesus
 *
 */
public class BBDataSaver {
	
	public static void write(String userName, Bat bat, ArrayList<Bonus> bonusList, ArrayList<Brick> brickList, ArrayList<Ball> ballList,
			ArrayList<Rocket> rocketList, ArrayList<Wall> wallList, Score score, Life life, Level level, AmmunitionCounter counter,
			Object[] config, float xReverseScale, float yReverseScale) {
		try {
			Connection connection = DataConnection.openConection();
			PreparedStatement prepStatement = connection.prepareStatement("Select * from BAT where nick = ?;");
			prepStatement.setString(1, userName);
			ResultSet resultSet = prepStatement.executeQuery();
			bat.resize(xReverseScale, yReverseScale);
			if(resultSet.next()) {
				resultSet.close();
				prepStatement.close();
				//Deletes user previous SAVEDATA.
				prepStatement = connection.prepareStatement("Delete from BAT where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BONUS where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BRICK where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BALL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from ROCKET where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from WALL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from SCORE where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from LIFE where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from LEVEL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from AMMO where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from CONFIGSET where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
			} else {
				resultSet.close();
				prepStatement.close();
			}
			//Creates new SAVEDATA.
			prepStatement = connection.prepareStatement("Insert into BAT values(?, ?, ?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer)bat.getX()).toString());
			prepStatement.setString(3, ((Integer)bat.getY()).toString());
			prepStatement.setString(4, ((Integer)((int)bat.getDX())).toString());
			prepStatement.setString(5, ((Integer)((int)bat.getDY())).toString());
			prepStatement.setString(6, ((Integer)bat.getAmmo()).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			for(int i = 0; i < bonusList.size(); i++) {
				bonusList.get(i).resize(xReverseScale, yReverseScale);
				prepStatement = connection.prepareStatement("Insert into BONUS (nick, x, y, dx, dy, type) values(?, ?, ?, ?, ?, ?);");
				prepStatement.setString(1, userName);
				prepStatement.setString(2, ((Integer)bonusList.get(i).getX()).toString());
				prepStatement.setString(3, ((Integer)bonusList.get(i).getY()).toString());
				prepStatement.setString(4, ((Integer)((int)bonusList.get(i).getDX())).toString());
				prepStatement.setString(5, ((Integer)((int)bonusList.get(i).getDY())).toString());
				prepStatement.setString(6, bonusList.get(i).getType().bonusTypeToInteger().toString());
				prepStatement.executeUpdate();
				prepStatement.close();
			}
			for(int i = 0; i < brickList.size(); i++) {
				brickList.get(i).resize(xReverseScale, yReverseScale);
				prepStatement = connection.prepareStatement("Insert into BRICK (nick, x, y, type, lives) values(?, ?, ?, ?, ?);");
				prepStatement.setString(1, userName);
				prepStatement.setString(2, ((Integer) brickList.get(i).getX()).toString());
				prepStatement.setString(3, ((Integer) brickList.get(i).getY()).toString());
				prepStatement.setString(4, brickList.get(i).getColor().brickColorToInteger().toString());
				prepStatement.setString(5, ((Integer) brickList.get(i).getLives()).toString());
				prepStatement.executeUpdate();
				prepStatement.close();
			}
			for(int i = 0; i < wallList.size(); i++) {
				wallList.get(i).resize(xReverseScale, yReverseScale);
				prepStatement = connection.prepareStatement("Insert into WALL (nick, x, y, type) values(?, ?, ?, ?);");
				prepStatement.setString(1, userName);
				prepStatement.setString(2, ((Integer)wallList.get(i).getX()).toString());
				prepStatement.setString(3, ((Integer)wallList.get(i).getY()).toString());
				prepStatement.setString(4, wallList.get(i).getType().wallTypeToInteger().toString());
				prepStatement.executeUpdate();
				prepStatement.close();
			}
			for(int i = 0; i < ballList.size(); i++) {
				ballList.get(i).resize(xReverseScale, yReverseScale);
				prepStatement = connection.prepareStatement("Insert into BALL (nick, x, y, dx, dy) values(?, ?, ?, ?, ?);");
				prepStatement.setString(1, userName);
				prepStatement.setString(2, ((Integer)ballList.get(i).getX()).toString());
				prepStatement.setString(3, ((Integer)ballList.get(i).getY()).toString());
				prepStatement.setString(4, ((Integer)((int)ballList.get(i).getDX())).toString());
				prepStatement.setString(5, ((Integer)((int)ballList.get(i).getDY())).toString());
				prepStatement.executeUpdate();
				prepStatement.close();
			}
			for(int i = 0; i < rocketList.size(); i++) {
				rocketList.get(i).resize(xReverseScale, yReverseScale);
				prepStatement = connection.prepareStatement("Insert into ROCKET (nick, x, y, dx, dy) values(?, ?, ?, ?, ?);");
				prepStatement.setString(1, userName);
				prepStatement.setString(2, ((Integer)rocketList.get(i).getX()).toString());
				prepStatement.setString(3, ((Integer)rocketList.get(i).getY()).toString());
				prepStatement.setString(4, ((Integer)((int)rocketList.get(i).getDX())).toString());
				prepStatement.setString(5, ((Integer)((int)rocketList.get(i).getDY())).toString());
				prepStatement.executeUpdate();
				prepStatement.close();
			}
			score.resize(xReverseScale, yReverseScale);
			prepStatement = connection.prepareStatement("Insert into SCORE values(?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer) score.getX()).toString());
			prepStatement.setString(3, ((Integer) score.getY()).toString());
			prepStatement.setString(4, ((Long) score.getPoints()).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			life.resize(xReverseScale, yReverseScale);
			prepStatement = connection.prepareStatement("Insert into LIFE values(?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer) life.getX()).toString());
			prepStatement.setString(3, ((Integer) life.getY()).toString());
			prepStatement.setString(4, ((Integer) life.getLives()).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			level.resize(xReverseScale, yReverseScale);
			prepStatement = connection.prepareStatement("Insert into LEVEL values(?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer) level.getX()).toString());
			prepStatement.setString(3, ((Integer) level.getY()).toString());
			prepStatement.setString(4, ((Integer) level.getLevel()).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			counter.resize(xReverseScale, yReverseScale);
			prepStatement = connection.prepareStatement("Insert into AMMO values(?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer) counter.getX()).toString());
			prepStatement.setString(3, ((Integer) counter.getY()).toString());
			prepStatement.setString(4, ((Integer) bat.getAmmo()).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			prepStatement = connection.prepareStatement("Insert into CONFIGSET values(?, ?, ?, ?, ?, ?, ?);");
			prepStatement.setString(1, userName);
			prepStatement.setString(2, ((Integer)config[0]).toString());
			prepStatement.setString(3, ((Integer)config[1]).toString());
			prepStatement.setString(4, ((Integer)config[2]).toString());
			prepStatement.setString(5, ((PercentNumber)config[3]).percentNumberToInteger().toString());
			prepStatement.setString(6, ((Integer)config[4]).toString());
			prepStatement.setString(7, ((Integer)config[5]).toString());
			prepStatement.executeUpdate();
			prepStatement.close();
			connection.close();
		} catch(SQLException e) {
			System.out.println(e.getMessage());
		}
	}
	
	public static ArrayList<Object> load(String userName, float xScale, float yScale) throws NoSaveException {
		ArrayList<Object> list = new ArrayList<Object>();
		try{
			Connection connection = DataConnection.openConection();
			PreparedStatement preparedStatement = connection.prepareStatement("Select * from BAT where nick = ?;");
			preparedStatement.setString(1, userName);
			ResultSet resultSet = preparedStatement.executeQuery();
			if(resultSet.next()) {
				resultSet.close();
				preparedStatement.close();
				//Loads all the entities from all the tables into the arrayList.
				preparedStatement = connection.prepareStatement("Select * from BAT where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new Bat(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
						resultSet.getInt("dx"), resultSet.getInt("dy"), xScale, yScale, resultSet.getInt("ammo")));
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from BONUS where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				while(resultSet.next()) {
					list.add(new Bonus(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
							resultSet.getInt("dx"), resultSet.getInt("dy"),BonusType.intToBonusType(resultSet.getInt("type")),
							xScale, yScale));
				}
				preparedStatement = connection.prepareStatement("Select * from BRICK where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				while(resultSet.next()) {
					list.add(new Brick(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
							BrickColor.intToBrickColor(resultSet.getInt("type")), resultSet.getInt("lives"), xScale, yScale));
				}
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from WALL where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				while(resultSet.next()) {
					list.add(new Wall(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
							WallType.intToWallType(resultSet.getInt("type")), xScale, yScale));
				}
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from BALL where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				while(resultSet.next()) {
					list.add(new Ball(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
							resultSet.getInt("dx"), resultSet.getInt("dy"), xScale, yScale));
				}
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from ROCKET where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				while(resultSet.next()) {
					list.add(new Rocket(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
							resultSet.getInt("dx"), resultSet.getInt("dy"), xScale, yScale));
				}
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from SCORE where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new Score(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
						xScale, yScale, Float.valueOf(resultSet.getString("score")).longValue()));
				preparedStatement = connection.prepareStatement("Select * from LIFE where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new Life(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
						resultSet.getInt("lives"), xScale, yScale));
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from LEVEL where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new Level(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
						xScale, yScale, resultSet.getInt("level")));
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from AMMO where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new AmmunitionCounter(Math.round(resultSet.getInt("x") * xScale), Math.round(resultSet.getInt("y") * yScale),
						xScale, yScale, resultSet.getInt("ammo")));
				resultSet.close();
				preparedStatement.close();
				preparedStatement = connection.prepareStatement("Select * from CONFIGSET where nick = ?;");
				preparedStatement.setString(1, userName);
				resultSet = preparedStatement.executeQuery();
				list.add(new Object[] {resultSet.getInt("ballSpeed"), resultSet.getInt("batSpeed"), resultSet.getInt("bonusSpeed"),
						PercentNumber.intToPercentNumber(resultSet.getInt("percent")), resultSet.getInt("row"), resultSet.getInt("column")});
				resultSet.close();
				preparedStatement.close();
				connection.close();
			} else {
				resultSet.close();
				preparedStatement.close();
				connection.close();
				throw new NoSaveException();
			}
		} catch(SQLException e) {
			System.out.println(e.getMessage());
		}
		return list;
	}
	
	public static void delete(String userName) {
		try {
			if(hasSave(userName)) {
				Connection connection = DataConnection.openConection();
				PreparedStatement prepStatement = connection.prepareStatement("Delete from BAT where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BONUS where nick = ?;");
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BRICK where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from BALL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from ROCKET where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from WALL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from SCORE where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from LIFE where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from LEVEL where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from AMMO where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				prepStatement = connection.prepareStatement("Delete from CONFIGSET where nick = ?;");
				prepStatement.setString(1, userName);
				prepStatement.executeUpdate();
				prepStatement.close();
				connection.close();
			}
		}catch(SQLException e) {
			
		}
	}
	
	public static boolean hasSave(String userName) {
		boolean hasSave = false;
		try {
			Connection connection = DataConnection.openConection();
			PreparedStatement prepStatement = connection.prepareStatement("Select * from BAT where nick = ?;");
			prepStatement.setString(1, userName);
			ResultSet resultSet = prepStatement.executeQuery();
			hasSave = resultSet.next();
			resultSet.close();
			prepStatement.close();
			connection.close();
		} catch(SQLException e) {
			System.out.println(e.getMessage());
		}
		return hasSave;
	}
}
